//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<IBuffer.h>
///	@path	~/src/object/
///	@date	2007/11/20
///	@desc	Varying size buffer class for arbitrary data.

#pragma once

#include "xeres.h"

#include "object/IObject.h"

namespace xeres {

	/*!
		\ingroup iobject_module

		\class	IBuffer
		\brief	Special IObject class for encapsulating a varying buffer.
		\details
			IBuffer is used for storing arbitrary data or varying size binary. It can be manipulated as an IObject,
			and stores data for concatenating user defined objects.

			\eg Using IBuffer to store user data.
			\code
				// We store a record in IBuffer and encapsulate it to a variable for any other usage.
				struct Record
				{
					char	name[64];
					int		equipment;
					int		weapon;
				};

				// Allocate IBuffer.
				Ref<IBuffer> buffer = IBuffer::Create( sizeof(Record) );
				Record * pRecord = static_cast<Record*>( buffer->GetData() );

				// Use data.
				strcpy( pRecord->name , "David" );

				// Create variable
				Ref<CVar> cvar = new CVar;
				cvar->SetObject( buffer );

				// Now we've got IVar, can use it as script variable or network package attachment.
				// ...

			\endcode

		\sa		IVar

	*/
	class IBuffer : public IObject
	{
	private:

		/// \name Constructor & Destructor
		//@{

		/// \ctor
		IBuffer( size_t data_size );

		/// \dtor
		virtual ~IBuffer( void );

		//@}

		DECL_IOBJECT_INHERITANCE( IBuffer , IObject );
		DECL_OBJECT_COMPATIBLE( IBuffer );

	public:

		/// \name RTTI interface
		//@{

		/*!
			\brief		Get class name of this class. For RTTI.
			\details	The function should be defined by \ref DECL_IOBJECT_CLASS,
						but in this special implementation, we define it manually for customized registration.
			\return		Class name of this class.
		*/
		virtual const WString& GetClassName( void ) const;

		/*!
			\brief		Get ancient (super) class name. For RTTI.
			\details	The function should be defined by \ref DECL_IOBJECT_CLASS,
						but in this special implementation, we define it manually for customized registration.
			\return		Ancient class name of this class.
		*/
		virtual const WString& GetAncientName( void ) const;

		/*!
			\brief		Get class ID of this class.
			\details	The function should be defined by \ref DECL_IOBJECT_CLASS,
						but in this special implementation, we define it manually for customized registration.
			\return		Class ID of this class.
		*/
		virtual const ClassID GetClassID( void ) const;

		/*!
			\brief		Get ancient class ID of this class.
			\details	The function should be defined by \ref DECL_IOBJECT_CLASS,
						but in this special implementation, we define it manually for customized registration.
			\return		Ancient class ID of this class.
		*/
		virtual const ClassID GetAncientID( void ) const;

		/*!
			\brief		Get class name statically.
			\details	The function should be defined by \ref DECL_IOBJECT_CLASS,
						but in this special implementation, we define it manually for customized registration.
			\return		Class name of this class.
		*/
		static const WString& StaticClassName( void );

		/*!
			\brief		Get class ID statically.
			\details	The function should be defined by \ref DECL_IOBJECT_CLASS,
						but in this special implementation, we define it manually for customized registration.
			\return		Class ID of this class.
		*/
		static const ClassID StaticClassID( void );

		//@}

		/// \name Buffer Management
		//@{

		/*!
			\brief		Get buffer size.
			\return		The size of buffer in byte.
		*/
		size_t GetSize( void ) const { return m_size; }

		/*!
			\brief		Get buffer data(constant).
			\return		The address of buffer.
		*/
		const void * GetData( void ) const { return m_data; }

		/*!
			\brief		Get buffer data.
			\return		The address of buffer.
		*/
		void * GetData( void ) { return m_data; }

		/*!
			\brief		Duplicate buffer data.
			\details	Duplicate buffer with a memory copy operation.
		*/
		RefPass<IBuffer> Duplciate( void ) const;

		/*!
			\brief		Create new buffer.
			\details	IBuffer cannot be created by either new operator or ObjectFactory::CreateObject.
						Use this function to create new IBuffer with fixed size.<BR>
						The returned buffer space is cleared with empty data.
			\param[in]	buffer_size		Buffer size in byte.
			\return		New IBuffer instance.
		*/
		static RefPass<IBuffer> Create( size_t buffer_size );

		/// \brief	Delete operator.
		void operator delete ( void * ptr );

	private:

		//@}

		// dummy class id
		static ClassID s_IBufferClassID;

		// data
		size_t		m_size;
		byte		m_data[1];

		// friend
		friend class IObject;
	};

} // namespace xeres
